using System;
using System.Collections.Generic;

internal static class MessengerInternal
{
	public static void OnListenerAdding(string eventType, Delegate listenerBeingAdded)
	{
		if (!MessengerInternal.eventTable.ContainsKey(eventType))
		{
			MessengerInternal.eventTable.Add(eventType, null);
		}
		Delegate @delegate = MessengerInternal.eventTable[eventType];
		if (@delegate != null && @delegate.GetType() != listenerBeingAdded.GetType())
		{
			throw new MessengerInternal.ListenerException(string.Format("Attempting to add listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being added has type {2}", eventType, @delegate.GetType().Name, listenerBeingAdded.GetType().Name));
		}
	}

	public static void OnListenerRemoving(string eventType, Delegate listenerBeingRemoved)
	{
		if (!MessengerInternal.eventTable.ContainsKey(eventType))
		{
			throw new MessengerInternal.ListenerException(string.Format("Attempting to remove listener for type {0} but Messenger doesn't know about this event type.", eventType));
		}
		Delegate @delegate = MessengerInternal.eventTable[eventType];
		if (@delegate == null)
		{
			throw new MessengerInternal.ListenerException(string.Format("Attempting to remove listener with for event type {0} but current listener is null.", eventType));
		}
		if (@delegate.GetType() != listenerBeingRemoved.GetType())
		{
			throw new MessengerInternal.ListenerException(string.Format("Attempting to remove listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being removed has type {2}", eventType, @delegate.GetType().Name, listenerBeingRemoved.GetType().Name));
		}
	}

	public static void OnListenerRemoved(string eventType)
	{
		if (MessengerInternal.eventTable[eventType] == null)
		{
			MessengerInternal.eventTable.Remove(eventType);
		}
	}

	public static void OnBroadcasting(string eventType, MessengerMode mode)
	{
		if (mode == MessengerMode.REQUIRE_LISTENER && !MessengerInternal.eventTable.ContainsKey(eventType))
		{
			throw new MessengerInternal.BroadcastException(string.Format("Broadcasting message {0} but no listener found.", eventType));
		}
	}

	public static MessengerInternal.BroadcastException CreateBroadcastSignatureException(string eventType)
	{
		return new MessengerInternal.BroadcastException(string.Format("Broadcasting message {0} but listeners have a different signature than the broadcaster.", eventType));
	}

	public static Dictionary<string, Delegate> eventTable = new Dictionary<string, Delegate>();

	public static readonly MessengerMode DEFAULT_MODE = MessengerMode.REQUIRE_LISTENER;

	public class BroadcastException : Exception
	{
		public BroadcastException(string msg) : base(msg)
		{
		}
	}

	public class ListenerException : Exception
	{
		public ListenerException(string msg) : base(msg)
		{
		}
	}
}
